

    /*global google, $, jQuery */
    /*jslint browser: true */

    var sgvizler = {

        goUltraLite: function (callback) {
            // Loads nothing but the visualization package. Needed for DataTable.
            google.load('visualization', '1.0');
            google.setOnLoadCallback(function () { sgvizler.run(callback); });
        },
        goLite: function (callback) {
            // UltraLite + all implemented Google Charts.
            google.load('visualization',
                        '1.0',
                        {'packages':
                         ['annotatedtimeline',
                          'corechart',
                          'gauge',
                          'geomap',
                          'geochart',
                          'imagesparkline',
                          'map',
                          'orgchart',
                          'table',
                          'motionchart',
                          'treemap'
                         ]
                        }
                       );

            google.setOnLoadCallback(function () { sgvizler.run(callback); });
        },
        go: function (callback) {
            // Everything: Lite + all external js libs.
            this.loadLibs();
            this.goLite(callback);
        },
        run: function (callback) {
            this.charts.loadCharts();
            this.drawFormQuery();
            this.drawContainerQueries();
            if (callback) { callback(); }
        },

        loadLibs: function () {
            var i,
                libs;

            if (sgvizler.ui.isElement(sgvizler.ui.id.script)) {
                this.option.homefolder = $('#' + sgvizler.ui.id.script).attr('src').replace(/sgvizler\.js$/, "");
                this.option.libfolder = this.option.homefolder + "lib/";
            }

            libs = ['//cdnjs.cloudflare.com/ajax/libs/d3/2.10.0/d3.v2.min.js',
                    this.option.libfolder + 'raphael-dracula.pack.min.js'];

            // load external libraries.
            for (i = 0; i < libs.length; i += 1) {
                $.ajax(libs[i], { dataType: "script", async: false });
            }

            // load stylesheet.
            $('head').append('<link rel="stylesheet" href="' + this.option.homefolder + 'sgvizler.chart.css" type="text/css" />');
        },

        drawFormQuery: function () {
            var params = sgvizler.ui.getUrlParams(),
                query = new sgvizler.query(sgvizler.ui.id.chartCon);

            if (sgvizler.ui.isElement(sgvizler.ui.id.chartCon) && params.query) {
                query.draw({ query: params.query,
                             chart: params.chart,
                             endpoint: params.endpoint,
                             format: params.format },
                           { width: params.width,
                             height: params.height }
                          );
            }
            sgvizler.ui.displayUI(query);
        },

        drawContainerQueries: function () {
            $('[' + this.ui.attr.prefix + 'query]').each(function () {
                var query = new sgvizler.query($(this).attr("id"));
                query.draw();
            });
        },

        // kept in separate files:
        option: {},   // settings, global variables.
        chart: {},    // the set of user-defined rendering functions.
        charts: {},   // functions for handling rendering functions.
        preprocess: {},   // functions for processing datatables before drawing.
        parser: {},   // SPARQL results XML/JSON parser.
        ui: {}       // html get/set functions.
    };

    jQuery.ajaxSetup({
        accepts: {
            xml:   "application/sparql-results+xml",
            json:  "application/sparql-results+json",
            jsonp: "application/sparql-results+json"
        }
    });
